import 'package:cross_file/cross_file.dart';
import 'package:image_picker/types/camera_device.dart';
import 'package:image_picker/types/image_options.dart';
import 'package:image_picker/types/image_source.dart';
import 'package:image_picker/types/lost_data_response.dart';
import 'package:image_picker/types/multi_image_picker_options.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';

import 'image_picker_method_channel.dart';

abstract class ImagePickerPlatform extends PlatformInterface {
  /// Constructs a ImagePickerPlatform.
  ImagePickerPlatform() : super(token: _token);

  static final Object _token = Object();

  static ImagePickerPlatform _instance = MethodChannelImagePicker();

  /// The default instance of [ImagePickerPlatform] to use.
  ///
  /// Defaults to [MethodChannelImagePicker].
  static ImagePickerPlatform get instance => _instance;

  /// Platform-specific implementations should set this with their own
  /// platform-specific class that extends [ImagePickerPlatform] when
  /// they register themselves.
  static set instance(ImagePickerPlatform instance) {
    PlatformInterface.verifyToken(instance, _token);
    _instance = instance;
  }

  Future<XFile?> getImage({
    double? maxWidth,
    double? maxHeight,
    int? imageQuality,
    CameraDevice preferredCameraDevice = CameraDevice.rear,
  }) {
    throw UnimplementedError('getImage() has not been implemented.');
  }

  Future<List<XFile>?> getMultiImage({
    double? maxWidth,
    double? maxHeight,
    int? imageQuality,
  }) {
    throw UnimplementedError('getMultiImage() has not been implemented.');
  }

  Future<LostDataResponse> getLostData() {
    throw UnimplementedError('getLostData() has not been implemented.');
  }

  Future<XFile?> getImageFromSource({
    ImagePickerOptions options = const ImagePickerOptions(),
  }) {
    return getImage(
      maxHeight: options.maxHeight,
      maxWidth: options.maxWidth,
      imageQuality: options.imageQuality,
      preferredCameraDevice: options.preferredCameraDevice,
    );
  }

  /// Returns a [List<XFile>] with the images that were picked.
  ///
  /// The images come from the [ImageSource.gallery].
  ///
  /// The `options` argument controls additional settings that can be used when
  /// picking an image. See [MultiImagePickerOptions] for more details.
  ///
  /// If no images were picked, returns an empty list.
  Future<List<XFile>> getMultiImageWithOptions({
    MultiImagePickerOptions options = const MultiImagePickerOptions(),
  }) async {
    final List<XFile>? pickedImages = await getMultiImage(
      maxWidth: options.imageOptions.maxWidth,
      maxHeight: options.imageOptions.maxHeight,
      imageQuality: options.imageOptions.imageQuality,
    );
    return pickedImages ?? <XFile>[];
  }

  /// Returns true if the implementation supports [source].
  ///
  /// Defaults to true for the original image sources, `gallery` and `camera`,
  /// for backwards compatibility.
  bool supportsImageSource(ImageSource source) {
    return source == ImageSource.gallery || source == ImageSource.camera;
  }
}
